import { useDispatch, useSelector } from 'react-redux'
import { useEffect, useRef } from 'react'
// 通过 usePersistFn，可以保证函数地址永远不会变化。
import { usePersistFn } from 'ahooks'
// 下拉刷新组件
import { PullToRefresh } from 'antd-mobile-v5'
import MoreAction from '../MoreAction'
import { getArticles, getMoreArticles } from '@/store/actions'
import ArticleItem from '@/components/ArticleItem'

import styles from './index.module.scss'

const ArticleList = ({ channelId, activeId }) => {
  const dispatch = useDispatch()
  // 获取当前数据状态
  const { articles } = useSelector(state => state.home)

  // 加载中   通过ref属性来控制滚动条页面的数据获取
  const isLoadingRef = useRef(false)

  // 控制列表内容滚动  初始值为null
  const containerRef = useRef(null)

  // 创建列表底部控制距离页面底部距离
  const bottomRef = useRef(null)

  // 根据当前频道id获取文章数据
  // 坑：这里的文章数据有可能获取不到，为了防止报错，这里需要在没有获取到数据的时候给个空值
  // ?? 空值合并操作符    当 ?? 左侧的值是 null 或 undefined 的情况下，会返回 ?? 右侧值
  const channelArticle = articles[channelId] ?? {}
  const { list, prevTime } = channelArticle

  // 滚动事件
  const handleScroll = usePersistFn(async () => {
    // 滚动内容底部距离
    // console.log(111);
    // getBoundingClientRect **方法返回元素的大小及其相对于视口的位置**JS一个DOMRect对象方法，控制矩形
    // ref top - bottom 底部到页面高度 减 页面高度
    const { top } = bottomRef.current.getBoundingClientRect()
    // 滚动内容顶部距离
    const { bottom } = containerRef.current.getBoundingClientRect()
    // 当底部距离小于250刷新获取文章列表
    if (top - bottom <= 250) {
      // 频道ID和当前频道ID不同直接跳出，以下代码不执行
      // 这里计算的是当前页的距离，要获取的数据是当前页，不影响其他频道
      if (channelId !== activeId) return
      // 请求前一页历史数据的时间戳
      if (!prevTime) return
      // 判断数据是否加载中
      if (isLoadingRef.current) return
      // console.log(isLoadingRef);
      isLoadingRef.current = true
      // 发请求拿数据   参数是当前频道ID和时间戳
      await dispatch(getMoreArticles(channelId, prevTime))
      isLoadingRef.current = false
    }
  })

  // 监听页面滚动
  useEffect(() => {
    // 列表数据元素
    const containerDOM = containerRef.current
    containerDOM.addEventListener('scroll', handleScroll)
    return () => {
      containerDOM.removeEventListener('scroll', handleScroll)
    }
  }, [handleScroll])

  useEffect(() => {
    // 只获取当前选中频道列表显示在页面
    if (channelId !== activeId) return

    // 判断当前频道有没有文章列表数据，
    if (list?.length > 0) return
    // 如果没有，就发请求获取；
    // 如果有就直接使用 redux 中已有的文章数据即可
    dispatch(getArticles(channelId, new Date()))
  }, [dispatch, channelId, activeId, list])

  // 下拉刷新列表
  const onRefresh = () => {
    dispatch(getArticles(channelId, new Date()))
  }

  // 渲染列表
  const renderArticleList = () => {
    // 没有数据不渲染,返回null
    if (!list) return null
    // 有数据在渲染
    return list.map(item => {
      // 数据中获取到的键
      const {
        art_id,
        // 作者名
        /* aut_id,*/ aut_name,
        comm_count,
        cover: { type, images },
        // 时间
        pubdate,
        title,
      } = item
      // map遍历后的数据状态
      const articleItemProps = {
        type,
        title,
        aut_name,
        comm_count,
        pubdate,
        images,
        isLogin: false,
      }
      return (
        <div key={art_id} className="article-item">
          {/* 文章列表中的每一项 */}
          <ArticleItem {...articleItemProps} />
        </div>
      )
    })
  }

  return (
    // ref 控制滚动效果 DOM操作
    <div
      className={styles.root}
      ref={containerRef}
      style={{ display: activeId === channelId ? 'block' : 'none' }}
    >
      <div className="articles">
        {/* 下拉触发刷新效果  onRefresh */}
        <PullToRefresh onRefresh={onRefresh}>
          {/* 要渲染的滚动列表 */}
          {renderArticleList()}
          {/* 通过ref控制底部dom元素判断距离 */}
          <div className="infinite" ref={bottomRef} />
        </PullToRefresh>
      </div>

      {/* 举报 */}
      <MoreAction visible={false} />
    </div>
  )
}

export default ArticleList
